/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_MEM_
#define	_INC_AK_MEM_

#include "ak_types.h"
#include "ak_queue.h"
#include "ak_tree.h"
#include "ak_lock.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 
** 	Here we Support the /Pool/Heap Memory Management.
**	1. Item 
**	2. Page
**	3. Slot / Slots / SLAB / Pool
**	4. GC
**	When GC is Enabled, We have 2 Type Slot:
** 	1. CacheAble.
**	Normally used with Large count of Small items. When GC, return memory Page to Slot.
**	When Incr, Alloc memory Page from pgAlk & System.
**	
**	2. Non-CacheAble.
**	Normally used with Small count of Large items. When GC, return memory Page to System.
**	When Incr, Alloc memory Page from pgAlk & System.
**	
**	3. 3-Level 
**	Heap - Pool - Slot
**	Use Heap to Limit the Total Size.
**	Use Pool to GC
**	Use Slot to Slab & Alloc.
*/

#define 	MPOOL_T_SIMP 		0X0000
#define 	MPOOL_T_SLAB		0X0001
#define 	MPOOL_T_SLAB_GC		0X0002
#define 	MPOOL_T_SLAB_GN		0X0003


#define 	MPOOL_PAGESZ 		0X100000
/* Pre-Declare */
struct _t_sysMPool;
struct _t_sysMHeap;
	
typedef struct{
	union{
		_t_rbnode		kNode;		/* Key-Value RB-Tree Node, We Strongly Used RB-Tree for Ordering & Hash & Random Seeking!! */
		_t_bnode		aNode;		/* Allocator Node */
	};
	/* Type / Allocator ID */
	unsigned int		type;
	union{
		int				alkId;
		unsigned int 	alkSize;
	};
	void 			* 	jar;		/* Jar of the Mem Item, GC */
}_t_sysMi;

typedef struct{
	_t_bnode 			node;
	_t_blist 			itQue;
	size_t 				size;
}_t_sysMPage;

typedef struct{
	_t_sysCS			lock; 	
	_t_blist 			pgQue; 	/* Page Que */
	_t_blist 			itQue;	/* Item Que */

	struct _t_sysMPool* pPool;
	unsigned int		sId;
	unsigned int 		pgSz;
	unsigned int 		itSz;
	unsigned int 		itCntP;/* Item Count in the Page */
}_t_sysMSlot;

typedef struct _t_sysMPool{
	_t_sysCS 			lock; 	
	_t_blist 			mAlk;
	_t_blist 			pgAlk;

	unsigned int 		type;	/* Pool Type */
	unsigned int 		pgSz;	
	unsigned int 		pgIncr;
	unsigned int 		slabCnt;
	
	/* Memory Limit */
	unsigned int  		itSzMax;
	int 				bGC;	/* Ex: If Need GC */

	struct _t_sysMHeap*	pHeap;

	/* Adding Statistic */
	unsigned int 		sCount;
	
	/* Slab Partition */
	size_t 		*		slabs; 	/* For Slab Use to Fast Judge */
	_t_sysMSlot * 		slots;	
}_t_sysMPool;

typedef struct _t_sysMHeap{
	_t_sysCS 			lock; 	
	/* Statistics */
	size_t 				mLimit;
	size_t				mAlloc; 
	
	unsigned int 		poolCnt;	
	_t_sysMPool 	* 	pools;
}_t_sysMHeap;

#define MPOOL_SET_HEAP(pPool, mHeap) 	((pPool)->pHeap  = (mHeap))
#define MPOOL_SET_SLOT(pPool, pSlot) 	((pPool)->slots  = (pSlot))
#define MPOOL_SET_SLAB(pPool, pSlab) 	((pPool)->slabs  = (pSlab))
#define MPOOL_SET_SCNT(pPool, sCnt) 	((pPool)->slabCnt= (sCnt))
#define MPOOL_SET_IMAX(pPool, szMax) 	((pPool)->itSzMax= (szMax)) 

#define MHEAP_SET_POOL(pHeap, pPool) 	((pHeap)->pools	 = (pPool)) 
#define MHEAP_SET_PCNT(pHeap, pCnt) 	((pHeap)->poolCnt= (pCnt)) 

extern  void 	MHeap_Init(_t_sysMHeap * pHeap, size_t mLimit);
extern	void	MHeap_InitEx(_t_sysMHeap * pHeap, size_t mLimit);

extern 	void 	MPool_Init(	_t_sysMPool * 	pPool, _t_sysMHeap * pHeap,
								size_t 			pgSz, 
								unsigned int 	itSzMax, 
								unsigned int 	pgIncr, 
								unsigned int 	pgInit,
								unsigned int 	type);

extern	void 	MSlot_Init(	_t_sysMSlot * 	pSlot, 
							_t_sysMPool * 	pPool, 
							unsigned int 	sId, 
							unsigned int 	itSz);

extern	int 	MSlab_Init(	_t_sysMPool * 	pPool, 	
							_t_sysMSlot * 	slots, 
							size_t 		 * 	slabs, 	
							int 			slabCnt, 
							int 			slabSz,
							int 			itAux);

extern	int 	MSlab_CalcCnt(unsigned int initSz, unsigned int maxSz, unsigned int * pCnt, unsigned int * pSz);

/* For Slab GC Pool */
extern	_t_sysMi *	MPool_AllocEx(_t_sysMPool * pPool, size_t size);
extern	int 		MPool_FreeEx(_t_sysMPool * pPool, _t_sysMi * pItem);

/* For Slab Pool */
extern	_t_sysMi *	MPool_Alloc(_t_sysMPool * pPool, size_t size);
extern	int 		MPool_Free(_t_sysMPool * pPool, _t_sysMi * pItem);
extern	int 		MPool_Pre(_t_sysMPool * pPool, unsigned int sId, unsigned int preCnt);

/* For Simple Pool */
extern	int 		MPool_ExecSi(_t_sysMPool * pPool, _t_cbentry * pCbEntry);

extern	void *		MPool_AllocSi(_t_sysMPool * pPool);
extern	int 		MPool_FreeSi(_t_sysMPool * pPool, void * pItem);
extern	int 		MPool_FreeSi2(_t_sysMPool * pPool, void * pItem);

extern	int 		MPool_AllocNi(_t_sysMPool * pPool, _t_blist * opQue, int count);
extern	int 		MPool_FreeNi(_t_sysMPool * pPool, _t_blist * opQue);
extern	int 		MPool_PreSx(_t_sysMPool * pPool, unsigned int preCnt);

extern	int 		MPool_GC(_t_sysMPool * pPool, unsigned int gcCnt);


/* Mem Pool Dump */
extern 	int  	MPool_Dump(_t_sysMPool  * pPool, char * outBuf, int bufLen);


/* Mem Command */
extern	int 	SMem_SetTraceLvl(int lvl);
extern	int 	SMem_GetTraceLvl(void);


#ifdef __cplusplus
}
#endif

#endif

